package reading.util.utils;

import org.apache.commons.lang3.time.DateFormatUtils;

import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.OffsetDateTime;
import java.time.temporal.ChronoField;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;


/**
 * 文件名称： 日期工具类
 * 内容摘要：
 * 创建人： tanxinwang
 * 创建日期：
 * 版本号： v1.0.0
 * 版权所有： (C)2001-2017
 * 修改记录1
 * 修改日期：
 * 版本号：
 * 修改人：
 * 修改内容：
 *
 * @author txw
 * @since 2017年1月13日
 **/
public class DateUtil {
    public static final String NULL_STAR = "null";
    /**
     * 日期格式
     */
    public static final String Y = "yyyy";
    public static final String Y_M = "yyyy-MM";
    public static final String Y_M_D = "yyyy-MM-dd";
    public static final String Y_M_D_HM = "yyyy-MM-dd HH:mm";
    public static final String Y_M_D_HMS = "yyyy-MM-dd HH:mm:ss";
    public static final String YMD = "yyyyMMdd";
    public static final String YMDHM = "yyyyMMddHHmm";
    public static final String YMDHMS = "yyyyMMddHHmmss";
    public static final String YMDHMSSSS="yyyyMMddHHmmssSSS";
    public static final String YMD_ = "yyyy/MM/dd";
    public static final String YMD_HM = "yyyy/MM/dd HH:mm";
    public static final String YMD_HMS = "yyyy/MM/dd HH:mm:ss";
    public static final String DATE_PATTERN = "HH:mm";

    /**
     * @param date 日期类型
     * @return String 日期字符串,格式：yyyy-MM-dd HH:mm:ss
     * @Description 将Date类型转换为字符串
     */
    public static String format(Date date) {
        return format(date, Y_M_D_HMS);
    }

    public static String formatYYMMDD(Date date) {
        return format(date, Y_M_D);
    }

    /**
     * @param date    日期类型
     * @param pattern 字符串格式 默认yyyy-MM-dd HH:mm:ss
     * @return String
     * @Description 将Date类型转换为指定格式字符串
     */
    public static String format(Date date, String pattern) {
        if (date == null) {
            return "";
        }
        if (StringUtil.isEmpty(pattern) || StringUtil.isBlank(pattern) || StringUtil.isEquals(NULL_STAR, pattern)) {
            pattern = Y_M_D_HMS;
        }
        return new SimpleDateFormat(pattern).format(date);
    }

    public static Date now() {
        Calendar calendar = Calendar.getInstance();
        return calendar.getTime();
    }

    /**
     * 按照pattern所指示的样式格式化日期,以String类型返回
     *
     * @param date
     * @param pattern
     * @return String
     */
    public static String format1(Date date, String pattern) {
        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
        return sdf.format(date);
    }

    /**
     * @param dateString
     * @return Date
     * @Description 将yyyy-MM-dd HH:mm:ss格式字符串转换成日期
     */
    public static Date format(String dateString) {
        return format(dateString, null);
    }

    /**
     * @param dateString 日期字符串
     * @param pattern    格式
     * @return Date
     * @Description 将字符串转换为Date类型
     */
    public static Date format(String dateString, String pattern) {
        if (StringUtil.isEmpty(pattern) || StringUtil.isBlank(pattern) || StringUtil.isEquals(NULL_STAR, pattern)) {
            pattern = Y_M_D_HMS;
        }
        if (StringUtil.isEmpty(dateString) || StringUtil.isBlank(dateString) || StringUtil.isEquals(NULL_STAR, dateString)) {
            return null;
        }
        Date d = null;
        try {
            d = new SimpleDateFormat(pattern).parse(dateString);
        } catch (ParseException pe) {
            throw new RuntimeException("日期转换异常：" + dateString);
        }
        return d;
    }

    /**
     * @return String
     * @Description 获取当前时间，格式:yyyyMMddHHmmss
     */
    public static String getCurrDateTime() {
        return DateFormatUtils.format(System.currentTimeMillis(), YMDHMS);
    }

    /**
     * @return String
     * @Description 获取当前日期，格式:yyyy-MM-dd
     */
    public static String getCurrDate() {
        return DateFormatUtils.format(System.currentTimeMillis(), Y_M_D);
    }

    public static String getCurrYMDate() {
        return DateFormatUtils.format(System.currentTimeMillis(), Y_M);
    }

    /**
     * 智能将日期转成字符串
     *
     * @param date
     * @return
     */
    public static String smartFormat(Date date) {
        String dateStr = null;
        if (date == null) {
            dateStr = "";
        } else {
            try {
                dateStr = format(date, Y_M_D_HMS);
                //时分秒
                final String s = " 00:00:00";
                final String m = "00:00";
                final String h = ":00";
                if (dateStr.endsWith(s)) {
                    dateStr = dateStr.substring(0, 10);
                }
                //时分

                else if (dateStr.endsWith(m)) {
                    dateStr = dateStr.substring(0, 16);
                }
                //秒  
                else if (dateStr.endsWith(h)) {
                    dateStr = dateStr.substring(0, 16);
                }
            } catch (Exception ex) {
                throw new IllegalArgumentException("转换日期失败: " + ex.getMessage(), ex);
            }
        }
        return dateStr;
    }

    /**
     * 本周一时间
     *
     * @param date
     * @return
     */
    public static Date getThisWeekMonday(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        // 获得当前日期是一个星期的第几天
        int dayWeek = cal.get(Calendar.DAY_OF_WEEK);
        if (1 == dayWeek) {
            cal.add(Calendar.DAY_OF_MONTH, -1);
        }
        // 设置一个星期的第一天，按中国的习惯一个星期的第一天是星期一
        cal.setFirstDayOfWeek(Calendar.MONDAY);
        // 获得当前日期是一个星期的第几天
        int day = cal.get(Calendar.DAY_OF_WEEK);
        // 根据日历的规则，给当前日期减去星期几与一个星期第一天的差值
        cal.add(Calendar.DATE, cal.getFirstDayOfWeek() - day);
        return cal.getTime();
    }

    /**
     * 上周一时间
     *
     * @param date
     * @return
     */
    public static Date geLastWeekMonday(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(getThisWeekMonday(date));
        cal.add(Calendar.DATE, -7);
        return cal.getTime();
    }


    /**
     * 以long型时间生成日历,以Calendar对象返回
     *
     * @return Calendar
     */
    static public Calendar getCalendar(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar;
    }

    /**
     * 获取指定日期的往后或往前i天的日期
     *
     * @param bizDate
     * @param i
     * @return
     */
    public static Date getDateByIndex(Date bizDate, int i) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(bizDate);
        calendar.add(Calendar.DATE, i);
        return calendar.getTime();
    }

    /**
     * 获取指定日期的往后或往前i月的日期
     *
     * @param bizDate
     * @param i
     * @return
     */
    public static Date getMonthByIndex(Date bizDate, int i) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(bizDate);
        calendar.add(Calendar.MONTH, i);
        return calendar.getTime();
    }


    /**
     * 获得上个月的第一天
     *
     * @return
     */
    public static Date getFirstDayOfLastMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.MONTH, -1);
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        calendar.set(Calendar.HOUR, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    /**
     * 获得当月的第一天
     *
     * @param date
     * @return
     */
    public static Date getFirstDayOfMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.MONTH, 0);
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        calendar.set(Calendar.HOUR, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    /**
     * 获得本周第一天
     *
     * @return
     */
    public static Date getWeekOfFisrtDay() {
        Calendar c = Calendar.getInstance();
        c.set(Calendar.DAY_OF_WEEK, 1);
        return c.getTime();
    }

    /**
     * 获得本周最后一天
     *
     * @return
     */
    public static Date getWeekOfLastDay() {
        Calendar c = Calendar.getInstance();
        c.set(Calendar.DAY_OF_WEEK, 7);
        return c.getTime();
    }

    /**
     * 获得当月的第一天
     *
     * @return
     */
    public static Date getMonthOfFirstDay() {
        Calendar c = Calendar.getInstance();
        c.set(Calendar.DAY_OF_MONTH, 1);
        return c.getTime();
    }

    /**
     * 获得当月的最后一天
     *
     * @return
     */
    public static Date getMonthOfLastDay() {
        Calendar c = Calendar.getInstance();
        c.add(Calendar.MONTH, 1);
        c.set(Calendar.DAY_OF_MONTH, 1);
        c.add(Calendar.DAY_OF_MONTH, -1);
        return c.getTime();
    }

    /**
     * 上一个月第一天
     *
     * @return
     */
    public static Date getFirstDayOfLastMonth() {
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.MONTH, -1);
        //设置为1号,当前日期既为本月第一天
        cal.set(Calendar.DAY_OF_MONTH, 1);
        return cal.getTime();
    }

    /**
     * 上一个月 最后一天
     *
     * @return
     */
    public static Date getLastMonthLastDay() {
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.DAY_OF_MONTH, 0);
        return cal.getTime();
    }

    /**
     * 本月第一天
     *
     * @return
     */
    public static Date getFirstDayOfMonth() {
        Calendar cal = Calendar.getInstance();
        //设置为1号,当前日期既为本月第一天
        cal.set(Calendar.DAY_OF_MONTH, 1);
        return cal.getTime();
    }

    /**
     * 本周第一天
     *
     * @return
     */
    public static Date getWeekStartDate() {
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        Date date = cal.getTime();
        return date;
    }

    /**
     * 获得本年的第一天
     *
     * @return
     */
    public static Date getYearOfFirstDay() {
        Calendar c = Calendar.getInstance();
        c.set(Calendar.DAY_OF_YEAR, 1);
        return c.getTime();
    }

    /**
     * 获得本年的最后一天
     *
     * @return
     */
    public static Date getYearOfLastDay() {
        Calendar c = Calendar.getInstance();
        c.add(Calendar.YEAR, 1);
        c.set(Calendar.DAY_OF_YEAR, 1);
        c.add(Calendar.DAY_OF_YEAR, -1);
        return c.getTime();
    }

    /**
     * 获得某年某月的第一天
     *
     * @param year
     * @param month
     * @return
     */
    public static Date getYearMonthFirstDay(int year, int month) {
        Calendar c = Calendar.getInstance();
        c.clear();
        c.set(Calendar.YEAR, year);
        c.set(Calendar.MONTH, month - 1);
        //日历中月份最小的天数
        int firstDay = c.getActualMinimum(Calendar.DAY_OF_MONTH);
        //格式化日期
        c.set(Calendar.DAY_OF_MONTH, firstDay);
        return c.getTime();
    }

    /**
     * 获得某年某月的最后一天
     *
     * @param year
     * @param month
     * @return
     */
    public static Date getYearMonthLastDay(int year, int month) {
        Calendar c = Calendar.getInstance();
        c.clear();
        c.set(Calendar.YEAR, year);
        c.set(Calendar.MONTH, month - 1);
        //日历中月份最小的天数
        int lastDay = c.getActualMaximum(Calendar.DAY_OF_MONTH);
        //格式化日期
        c.set(Calendar.DAY_OF_MONTH, lastDay);
        return c.getTime();
    }

    /**
     * 获得某年的第一天
     *
     * @param year
     * @return
     */
    public static Date getYearOfFirstDay(int year) {
        Calendar c = Calendar.getInstance();
        c.clear();
        c.set(Calendar.YEAR, year);
        c.set(Calendar.DAY_OF_YEAR, 1);
        return c.getTime();
    }

    /**
     * 获得某年的最后一天
     *
     * @param year
     * @return
     */
    public static Date getYearOfLastDay(int year) {
        Calendar c = Calendar.getInstance();
        c.clear();
        c.set(Calendar.YEAR, year);
        c.roll(Calendar.DAY_OF_YEAR, -1);
        return c.getTime();
    }

    /**
     * 获得上一个月的最后一天
     *
     * @param bizDate
     * @return
     */
    public static Date getLastDayOfLastMonth(Date bizDate) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(bizDate);
        calendar.add(Calendar.MONTH, -1);
        calendar.set(Calendar.HOUR, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        calendar.set(Calendar.MILLISECOND, 999);
        int day = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
        calendar.set(Calendar.DAY_OF_MONTH, day);
        return calendar.getTime();
    }


    /**
     * 获得上当月的最后一天
     *
     * @param bizDate
     * @return
     */
    public static Date getLastDayOfMonth(Date bizDate) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(bizDate);
        calendar.add(Calendar.MONTH, 0);
        calendar.set(Calendar.HOUR, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        calendar.set(Calendar.MILLISECOND, 999);
        int day = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
        calendar.set(Calendar.DAY_OF_MONTH, day);
        return calendar.getTime();
    }

    /**
     * 获得上当月的数量
     *
     * @param bizDate
     * @return
     */
    public static int getLastDayOfMonth1(Date bizDate) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(bizDate);
        return calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
    }


    /**
     * 获得上当月的数量
     *
     * @param bizDate
     * @return
     */
    public static int getMonth(Date bizDate) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(bizDate);
        return calendar.get(Calendar.MONTH) + 1;
    }


    /**
     * 获得上当月的数量
     *
     * @param bizDate
     * @return
     */
    public static Date getMonth1(Date bizDate, int i) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(bizDate);
        calendar.set(Calendar.MONTH, i - 1);
        return calendar.getTime();
    }


    /**
     * 返回是否超过某时间
     *
     * @param date
     * @return
     */
    public static boolean getDateByCheck(Date date) {
        boolean result = false;
        Calendar calendar = Calendar.getInstance(Locale.CHINA);
        calendar.setTime(new Date());
        Calendar calendar1 = Calendar.getInstance(Locale.CHINA);
        calendar1.setTime(date);
        if (calendar1.getTime().getTime() > calendar.getTime().getTime()) {
            result = true;
        }
        return result;
    }

    /**
     * 计算两个日期之间相差的天数
     *
     * @param smdate 较小的时间
     * @param bdate  较大的时间
     * @return 相差天数
     * @throws ParseException
     */
    public static int daysBetween(Date smdate, Date bdate) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        smdate = sdf.parse(sdf.format(smdate));
        bdate = sdf.parse(sdf.format(bdate));
        Calendar cal = Calendar.getInstance();
        cal.setTime(smdate);
        long time1 = cal.getTimeInMillis();
        cal.setTime(bdate);
        long time2 = cal.getTimeInMillis();
        long betweenDays = (time2 - time1) / (1000 * 3600 * 24);

        return Integer.parseInt(String.valueOf(betweenDays));
    }

    /**
     * 相差天数
     * @param smallDate
     * @param bigDate
     * @return
     */
    public static int daysBetween(OffsetDateTime smallDate, OffsetDateTime bigDate) {
        long time1 = smallDate.getLong(ChronoField.INSTANT_SECONDS);
        long time2 = bigDate.getLong(ChronoField.INSTANT_SECONDS);
        long betweenDays = (time2 - time1) / (3600 * 24);

        return Integer.parseInt(String.valueOf(betweenDays));
    }

    /**
     * 获得当前系统的系统日期时间,以TimeStamp对象返回结果
     *
     * @return Timestamp对象
     */
    public static Timestamp getSysTimestamp() {
        return new Timestamp(System.currentTimeMillis());
    }

    /**
     * 计算两个日期之间相差小时数
     *
     * @param smDate 较小的时间
     * @param bDate  较大的时间
     * @return 相差天数
     * @throws ParseException
     */
    public static int hoursBetween(Date smDate, Date bDate) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(smDate);
        long time1 = cal.getTimeInMillis();
        cal.setTime(bDate);
        long time2 = cal.getTimeInMillis();
        long betweenDays = (time2 - time1) / (1000 * 3600);

        return Integer.parseInt(String.valueOf(betweenDays));
    }

    /**
     * 计算两个日期之间相差分钟数
     *
     * @param smdate 较小的时间
     * @param bdate  较大的时间
     * @return 相差分钟数
     */
    public static long minuteBetween(Date smdate, Date bdate) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(smdate);
        long time1 = cal.getTimeInMillis();
        cal.setTime(bdate);
        long time2 = cal.getTimeInMillis();
        return (time2 - time1) / (1000 * 60);
    }

    public static long secondBetween(Date smdate, Date bdate) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(smdate);
        long time1 = cal.getTimeInMillis();
        cal.setTime(bdate);
        long time2 = cal.getTimeInMillis();
        return (time2 - time1) / (1000);
    }

    /**
     * 相差秒数
     * @param smallDate
     * @param bigDate
     * @return
     */
    public static int secondsBetween(OffsetDateTime smallDate, OffsetDateTime bigDate) {
        long time1 = smallDate.getLong(ChronoField.INSTANT_SECONDS);
        long time2 = bigDate.getLong(ChronoField.INSTANT_SECONDS);
        long betweenDays = (time2 - time1);

        return Integer.parseInt(String.valueOf(betweenDays));
    }
    /**
     * 获得当前系统的系统日期,以Date类型返回
     *
     * @return Date对象
     */
    public static Date getSysDate() {
        return new Date();
    }

    /**
     * 得到时间的id
     *
     * @return String
     */
    public static String getDateId() {
        return DateUtil.format(new Date(), "MMddHHmmss");
    }

    /**
     * 获取当前天数
     *
     * @param date
     * @return
     */
    public static int getDay(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(Calendar.DAY_OF_WEEK);
    }

    /**
     * 得到当前年
     *
     * @return
     */
    public static int getYear() {
        //得到Calendar的实例
        Calendar calendar = Calendar.getInstance();
        return calendar.get(Calendar.YEAR);
    }

    /**
     * 得到当前月
     *
     * @return
     */
    public static int getMonth() {
        //得到Calendar的实例
        Calendar calendar = Calendar.getInstance();
        return calendar.get(Calendar.MONTH) + 1;
    }

    /**
     * 得到几天后的日期
     *
     * @param @param  lastDay
     * @param @return 设定文件
     * @return Date    返回类型
     * @throws
     * @Title: getLastDay
     */
    public static Date getLastDay(int lastDay) {
        //取时间
        Date date = new Date();
        Calendar calendar = new GregorianCalendar();
        calendar.setTime(date);
        //把日期往后增加一天.整数往后推,负数往前移动
        calendar.add(Calendar.DATE, lastDay);
        //这个时间就是日期往后推一天的结果
        return calendar.getTime();
    }
}
